// CherryMerry ( Mikhail Tomilenko ), Reverse Entertainment, 2021-2024

#include "../Public/PlayerHealthManager.h"

#include <NifestGame/Core/Public/NF_GameInstance.h>
#include <NifestGame/Core/Public/NF_PlayerController.h>
#include <NifestGame/ActorComponents/Public/PlayerUIManager.h>
#include <NifestGame/ActorComponents/Public/PlayerMovementManager.h>
#include <NifestGame/ActorComponents/Public/PlayerCombatManager.h>
#include <NifestGame/Interfaces/Public/I_Core.h>

#include <Kismet/GameplayStatics.h>
#include <Blueprint/UserWidget.h>

UPlayerHealthManager::UPlayerHealthManager()
{
	PrimaryComponentTick.bCanEverTick = false;

	MaxTotemsAmount = 10;
	CurrentTotemsAmount = MaxTotemsAmount;
}


void UPlayerHealthManager::BeginPlay() {
	Super::BeginPlay();

	AActor* Owner = GetOwner();

	if (Owner)
	{
		GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Owner found")));
		Owner->OnTakeAnyDamage.AddDynamic(this, &UPlayerHealthManager::TakeDamage);

		bDead = false;
		bCanHealHealth = true;
		bCanHealShield = true;
		bCanDamage = true;
	}
}


void UPlayerHealthManager::DoDamage(float Damage)
{
	AActor* Owner = GetOwner();

	UPlayerMovementManager* MovementManager = Owner->FindComponentByClass<UPlayerMovementManager>();
	UPlayerCombatManager* CombatManager = Owner->FindComponentByClass<UPlayerCombatManager>();
	UPlayerUIManager* UI_Manager = Owner->FindComponentByClass<UPlayerUIManager>();

	if (!bDead)
	{
		if (bCanDamage && CombatManager->bBlockingDamage == false)
		{
			if (Damage <= 0)
			{
				GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Damage <= 0")));
				return;
			}
			else
			{
				GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("Damage > 0 \nDamage: %f"), Damage));
				if (CurrentShield > 0)
				{
					if (Damage >= CurrentShield)
					{
						CurrentShield = 0;
						UI_Manager->PlayerHUDMenu->PlayerShieldWidget->UpdateWidgetInfo(CurrentShield, MaxShield);
						GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("CurrentShield: %f"), CurrentShield));
					}
					else
					{
						CurrentShield = FMath::Clamp(CurrentShield - Damage, 0.0f, MaxShield);
						UI_Manager->PlayerHUDMenu->PlayerShieldWidget->UpdateWidgetInfo(CurrentShield, MaxShield);
						GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Blue, FString::Printf(TEXT("CurrentShield: %f"), CurrentShield));
					}
				}
				else if (CurrentHealth > 0)
				{
					if (Damage >= CurrentHealth)
					{
						CurrentHealth = 0;
						UI_Manager->PlayerHUDMenu->PlayerHealthWidget->UpdateWidgetInfo(CurrentHealth, MaxHealth);
						GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Red, FString::Printf(TEXT("CurrentHealth: %f\nYou dead :("), CurrentHealth));
						Death();
					}
					else
					{
						CurrentHealth = FMath::Clamp(CurrentHealth - Damage, 0.0f, MaxHealth);;
						UI_Manager->PlayerHUDMenu->PlayerHealthWidget->UpdateWidgetInfo(CurrentHealth, MaxHealth);
						GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, FString::Printf(TEXT("CurrentHealth: %f"), CurrentHealth));
					}
				}
			}
		}
		else if (!bCanDamage && CombatManager->bBlockingDamage == true)
		{
			MovementManager->UseStamina(25);
			if (MovementManager->CurrentStamina <= 0)
			{
				CombatManager->StopBlockIncomingDamage();
			}
		}
	}
}

void UPlayerHealthManager::DoHealHealth(float toHeal)
{
	if (bCanHealHealth)
	{
		if (CurrentHealth <= MaxHealth)
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, FString::Printf(TEXT("Current health: %f"), CurrentHealth));

			float HealthAfterHeal = CurrentHealth + toHeal;

			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Cyan, FString::Printf(TEXT("Health after heal: %f"), CurrentHealth));

			if (CurrentHealth == MaxHealth)
			{
				GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, FString::Printf(TEXT("CurrentHealth == MaxHealth")));
			}
			else if (HealthAfterHeal > MaxHealth)
			{
				CurrentHealth = MaxHealth;
				UIManager->PlayerHUDMenu->PlayerHealthWidget->UpdateWidgetInfo(CurrentHealth, MaxHealth);
				GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, FString::Printf(TEXT("CurrentHealth == MaxHealth")));
			}
			else if (CurrentHealth < MaxHealth)
			{
				CurrentHealth = CurrentHealth + toHeal;
				UIManager->PlayerHUDMenu->PlayerHealthWidget->UpdateWidgetInfo(CurrentHealth, MaxHealth);
				GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("Current health: %f"), CurrentHealth));
			}
		}
	}
}

void UPlayerHealthManager::DoHealShield(float toHeal)
{
	if (bCanHealShield)
	{
		if (CurrentShield <= MaxShield)
		{
			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Blue, FString::Printf(TEXT("Current Shield: %f"), CurrentShield));

			float ShieldAfterHeal = CurrentShield + toHeal;

			GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Cyan, FString::Printf(TEXT("Shield after heal: %f"), CurrentShield));

			if (CurrentShield == MaxShield)
			{
				GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, FString::Printf(TEXT("CurrentShield == MaxShield")));
			}
			else if (ShieldAfterHeal > MaxShield)
			{
				CurrentShield = MaxShield;
				UIManager->PlayerHUDMenu->PlayerShieldWidget->UpdateWidgetInfo(CurrentShield, MaxShield);
				GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Red, FString::Printf(TEXT("CurrentShield == MaxShield")));
			}
			else if (CurrentShield < MaxShield)
			{
				CurrentShield = CurrentShield + toHeal;
				UIManager->PlayerHUDMenu->PlayerShieldWidget->UpdateWidgetInfo(CurrentShield, MaxShield);
				GEngine->AddOnScreenDebugMessage(-1, 5.0f, FColor::Green, FString::Printf(TEXT("Current Shield: %f"), CurrentShield));
			}
		}
	}
}

void UPlayerHealthManager::Death()
{	
	AActor* Owner = GetOwner();
	UIManager = Owner->FindComponentByClass<UPlayerUIManager>();
	APlayerController* PlayerController = UGameplayStatics::GetPlayerController(this, 0);

	bDead = true;
	bCanDamage = false;
	bCanHealHealth = false;
	bCanHealShield = false;

	if (IsValid(Owner) && IsValid(PlayerController))
	{
		UIManager->CreateRespawnWidget();
		Owner->DisableInput(PlayerController);
	}
}

void UPlayerHealthManager::Respawn()
{
	AActor* Owner = GetOwner();
	UIManager = Owner->FindComponentByClass<UPlayerUIManager>();
	UNF_GameInstance* GameInstance = Cast<UNF_GameInstance>(UGameplayStatics::GetGameInstance(GetWorld()));

	if (CurrentTotemsAmount != 0)
	{
		bDead = false;
		bCanDamage = true;
		bCanHealHealth = true;
		bCanHealShield = true;

		UIManager->RemoveRespawnWidget();

		CurrentHealth = MaxHealth / 1.5;
		CurrentShield = MaxShield / 1.8;

		UseTotem();

		Owner->EnableInput(UGameplayStatics::GetPlayerController(GetWorld(), 0));

		II_Core* CoreInterface = Cast<II_Core>(Owner);
		if (CoreInterface)
		{
			CoreInterface->Execute_Initialize(Owner);
		}
	}
}

void UPlayerHealthManager::UpdateHealthAndShield(float NewMaxHealth, float NewMaxShield)
{
	MaxHealth = NewMaxHealth;
	MaxShield = NewMaxShield;
}

void UPlayerHealthManager::UseTotem()
{
	if (CurrentTotemsAmount != 0)
	{
		CurrentTotemsAmount -= 1;
	}
}

void UPlayerHealthManager::AddTotem()
{
	if (CurrentTotemsAmount != MaxTotemsAmount)
	{
		CurrentTotemsAmount += 1;
	}
}

void UPlayerHealthManager::TakeDamage(AActor* DamagedActor, float Damage, const UDamageType* DamageType, AController* InstigatedBy, AActor* DamageCauser)
{
	DoDamage(Damage);
}
